package com.homedo.microservice.open.service.gateway.zuul.autoconfig;

import com.homedo.common.util.Detect;
import com.homedo.microservice.open.service.gateway.util.ApplicationContextUtil;
import com.homedo.microservice.open.service.gateway.zuul.conf.RouteConf;
import com.homedo.microservice.open.service.gateway.zuul.conf.ZuulCommonConf;
import com.homedo.microservice.open.service.gateway.zuul.poller.ZuulFilterPollerFromDB;
import com.homedo.microservice.open.service.gateway.zuul.processor.LocalFilterProcessor;
import com.netflix.zuul.FilterFileManager;
import com.netflix.zuul.FilterLoader;
import com.netflix.zuul.FilterProcessor;
import com.netflix.zuul.filters.FilterRegistry;
import com.netflix.zuul.groovy.GroovyCompiler;
import com.netflix.zuul.groovy.GroovyFileFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.sql.DataSource;
import java.io.File;

@Configuration
public class ZuulInitAutoConfig {
    private static final Logger _LOGGER = LoggerFactory.getLogger(ZuulInitAutoConfig.class);
//
//    @Autowired
//    protected ZuulProperties zuulProperties;
//    @Autowired
//    protected ServerProperties server;

    @Autowired
    private DataSource dataSource;

    private ZuulCommonConf zuulCommonConf = ApplicationContextUtil.getApplicationContext().getBean(ZuulCommonConf.class);

//    @Bean
//    public LocalRouteLocator localRouteLocator() {
//        LocalRouteLocator localRouteLocator = new LocalRouteLocator(this.server.getServletPrefix(),
//                this.zuulProperties);
//        return localRouteLocator;
//    }


    //自动更新配置   不使用自带的方式 参见 ZuulCommonConfUpdateTask
//    @Bean
//    public AbstractConfiguration addApplicationPropertiesSource() {
//
//        String query = "SELECT * from d_config where application_name = '" + zuulCommonConf.getApplicationName() + "'";
//        String keyColumnName = "name";
//        String valueColumnName = "value";
//
//        PolledConfigurationSource source = new JDBCConfigurationSource(dataSource, query, keyColumnName, valueColumnName);
//        AbstractPollingScheduler scheduler = new FixedDelayPollingScheduler(0, 6000, false);
//
//        return new DynamicConfiguration(source, scheduler);
//    }

    @PostConstruct
    private void initZuul() throws Exception {


        _LOGGER.info("过滤器管理器即将启动...");


        final String preFiltersPath = zuulCommonConf.getZuulFilterPrePath();
        final String postFiltersPath = zuulCommonConf.getZuulFilterPostPath();
        final String routeFiltersPath = zuulCommonConf.getZuulFilterRoutePath();
        final String errorFiltersPath = zuulCommonConf.getZuulFilterErrorPath();
        final String customPath = zuulCommonConf.getZuulFilterCustomPath();

        this.initZuulFilterDir();

        try {
            //加载本地过滤器文件
            FilterProcessor.setProcessor(LocalFilterProcessor.getInstance());//设置自定义处理器
            FilterLoader.getInstance().setCompiler(new GroovyCompiler());
            FilterFileManager.setFilenameFilter(new GroovyFileFilter());

            if (!Detect.notEmpty(customPath)) {
                FilterFileManager.init(5, preFiltersPath, postFiltersPath, routeFiltersPath, errorFiltersPath);
            } else {
                FilterFileManager.init(5, preFiltersPath, postFiltersPath, routeFiltersPath, errorFiltersPath, customPath);
            }
            _LOGGER.info("过滤器管理器启动成功!");

        } catch (Exception ex) {
            _LOGGER.warn("[过滤器初始化加载出错,需检查问题,程序启动成功后会自动重试:{}]", ex.getMessage(), ex);
        }
        //从数据库加载过滤器
        startZuulFilterPollerFromDB();

//            MonitoringHelper.initMocks();//启动监控  CounterFactory 需要优化 https://www.jianshu.com/p/ebc0a2aef439

        RouteConf.start();//自动更新路由配置

    }

    private void initZuulFilterDir() {
        String preFiltersPath = zuulCommonConf.getZuulFilterPrePath();
        String postFiltersPath = zuulCommonConf.getZuulFilterPostPath();
        String routeFiltersPath = zuulCommonConf.getZuulFilterRoutePath();
        String errorFiltersPath = zuulCommonConf.getZuulFilterErrorPath();
        String customPath = zuulCommonConf.getZuulFilterCustomPath();

        File preFiltersFile = new File(preFiltersPath);
        File postFiltersFile = new File(postFiltersPath);
        File routeFiltersFile = new File(routeFiltersPath);
        File errorFiltersFile = new File(errorFiltersPath);

        if (!preFiltersFile.exists()) {
            preFiltersFile.mkdirs();
        }
        if (!postFiltersFile.exists()) {
            postFiltersFile.mkdirs();
        }
        if (!routeFiltersFile.exists()) {
            routeFiltersFile.mkdirs();
        }
        if (!errorFiltersFile.exists()) {
            errorFiltersFile.mkdirs();
        }
        if (Detect.notEmpty(customPath)) {
            File customFile = new File(customPath);
            if (!customFile.exists()) {
                customFile.mkdirs();
            }
        }
    }

    private void startZuulFilterPollerFromDB() {
        ZuulFilterPollerFromDB.start();
        _LOGGER.info("从数据库动态加载过滤器启动成功!");
    }

    @PreDestroy
    public void zuulDestroyed() {
        _LOGGER.info("清空资源...");
        FilterFileManager.shutdown();
        ZuulFilterPollerFromDB.stop();
        FilterRegistry.instance().getAllFilters().clear();
        RouteConf.stop();
    }

}
